home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
10,000 Great Games
/
10,000 Great Games.iso
/
Product
/
66
/
data1.cab
/
Source_Files
/
Src
/
Blit.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-16
|
16KB
|
653 lines
#include "stdafx.h"
void colormapped_blit(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, RECT *srcrect, char *colormap)
{
DDSURFACEDESC2 destsurf, srcsurf;
BYTE *d, *s;
ASSERT(colormap != 0);
// Lock surfaces
srcsurf.dwSize = sizeof(srcsurf);
while (!draw_ok(src->Lock(srcrect, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
destsurf.dwSize = sizeof(destsurf);
while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
// Get pointers
d = (BYTE *)destsurf.lpSurface;
s = (BYTE *)srcsurf.lpSurface;
// Get size of area to write
int w = destrect->right - destrect->left,
h = destrect->bottom - destrect->top;
int line_offset_src = srcsurf.lPitch - w,
line_offset_dest = destsurf.lPitch - w;
// Do the blit
__asm
{
mov ebx, colormap
mov esi, s
mov edi, d
// Make sure high order of eax is clear
xor eax, eax
mov edx, h
blit_loop_y:
mov ecx, w
blit_loop_x:
// Get source pixel shift it 8 bits to the left and add destination pixel
lodsb
shl ax, 8
add al, [edi]
// Lookup value from table and store it
mov al, [ebx + eax]
stosb
loop blit_loop_x
// Goto next line
add esi, line_offset_src
add edi, line_offset_dest
dec edx
jnz blit_loop_y
}
// Unlock surfaces
src->Unlock(srcrect);
dest->Unlock(destrect);
}
void rotated_blit(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
{
// Define: (x,y) is a point in the source surface,
// (u,v) is a point in the destination surface,
// (0,0) corresponds to the center of the image in both surfaces.
//
// A point in the source surface is then given as:
//
// (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
DDSURFACEDESC2 destsurf, srcsurf;
BYTE *d, *s;
ASSERT(scale != (fix)0);
// Lock surfaces
srcsurf.dwSize = sizeof(srcsurf);
while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
destsurf.dwSize = sizeof(destsurf);
while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
// Get destination pointer
d = (BYTE *)destsurf.lpSurface;
// Get size of area to write
int w = destrect->right - destrect->left,
h = destrect->bottom - destrect->top;
// Compute some frequently used variables
fix cos_angle_over_scale = cos(angle) / scale,
sin_angle_over_scale = sin(angle) / scale;
// Compute (dx,dy) for (du,dv)=(1,0)
#define dx_du cos_angle_over_scale
#define dy_du -sin_angle_over_scale
// Compute (dx,dy) for (du,dv)=(0,1)
#define dx_dv sin_angle_over_scale
#define dy_dv cos_angle_over_scale
// Compute the first pixel in the destination surface (su, sv)
int su = destrect->left - mx,
sv = destrect->top - my;
// Compute the first pixel in the source surface (sx, sy)
fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
// Transform to the source surface coordinates
sx += srcsurf.dwWidth / 2;
sy += srcsurf.dwHeight / 2;
// Do the blit
for (int v = 0; v < h; v++)
{
// (x,y) is the current pixel that has to be copied
fix x = sx,
y = sy;
for (int u = 0; u < w; u++, d++)
{
// (ix,iy) is the integer location of the current pixel
int ix = (int)x, iy = (int)y;
// Check if (ix,iy) is in the image
if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
{
// Compute the pixels location in memory
s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + ix;
// If not mask_color then write the pixel
if (*s != mask_color)
*d = *s;
}
// Update (x,y)
x += dx_du;
y += dy_du;
}
// Update the destination pointer to the next scanline
d += destsurf.lPitch - w;
// (sx,sy) is moved one scanline
sx += dx_dv;
sy += dy_dv;
}
// Unlock surfaces
src->Unlock(0);
dest->Unlock(destrect);
}
void rotated_colormapped_blit(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale, char *colormap)
{
// Define: (x,y) is a point in the source surface,
// (u,v) is a point in the destination surface,
// (0,0) corresponds to the center of the image in both surfaces.
//
// A point in the source surface is then given as:
//
// (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
DDSURFACEDESC2 destsurf, srcsurf;
BYTE *d, *s;
ASSERT(colormap != 0 && scale != (fix)0);
// Lock surfaces
srcsurf.dwSize = sizeof(srcsurf);
while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
destsurf.dwSize = sizeof(destsurf);
while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
// Get destination pointer
d = (BYTE *)destsurf.lpSurface;
// Get size of area to write
int w = destrect->right - destrect->left,
h = destrect->bottom - destrect->top;
// Compute some frequently used variables
fix cos_angle_over_scale = cos(angle) / scale,
sin_angle_over_scale = sin(angle) / scale;
// Compute (dx,dy) for (du,dv)=(1,0)
#define dx_du cos_angle_over_scale
#define dy_du -sin_angle_over_scale
// Compute (dx,dy) for (du,dv)=(0,1)
#define dx_dv sin_angle_over_scale
#define dy_dv cos_angle_over_scale
// Compute the first pixel in the destination surface (su, sv)
int su = destrect->left - mx,
sv = destrect->top - my;
// Compute the first pixel in the source surface (sx, sy)
fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
// Transform to the source surface coordinates
sx += srcsurf.dwWidth / 2;
sy += srcsurf.dwHeight / 2;
// Do the blit
for (int v = 0; v < h; v++)
{
// (x,y) is the current pixel that has to be copied
fix x = sx,
y = sy;
for (int u = 0; u < w; u++, d++)
{
// (ix,iy) is the integer location of the current pixel
int ix = (int)x, iy = (int)y;
// Check if (ix,iy) is in the image
if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
{
// Compute the pixels location in memory
s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + ix;
// Write the pixel
*d = colormap[*d + (*s << 8)];
}
// Update (x,y)
x += dx_du;
y += dy_du;
}
// Update the destination pointer to the next scanline
d += destsurf.lPitch - w;
// (sx,sy) is moved one scanline
sx += dx_dv;
sy += dy_dv;
}
// Unlock surfaces
src->Unlock(0);
dest->Unlock(destrect);
}
void rotated_blit16(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
{
// Define: (x,y) is a point in the source surface,
// (u,v) is a point in the destination surface,
// (0,0) corresponds to the center of the image in both surfaces.
//
// A point in the source surface is then given as:
//
// (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
DDSURFACEDESC2 destsurf, srcsurf;
BYTE *d, *s;
ASSERT(scale != (fix)0);
// Lock surfaces
srcsurf.dwSize = sizeof(srcsurf);
while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
destsurf.dwSize = sizeof(destsurf);
while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
// Get destination pointer
d = (BYTE *)destsurf.lpSurface;
// Get size of area to write
int w = destrect->right - destrect->left,
h = destrect->bottom - destrect->top;
// Compute some frequently used variables
fix cos_angle_over_scale = cos(angle) / scale,
sin_angle_over_scale = sin(angle) / scale;
// Compute (dx,dy) for (du,dv)=(1,0)
#define dx_du cos_angle_over_scale
#define dy_du -sin_angle_over_scale
// Compute (dx,dy) for (du,dv)=(0,1)
#define dx_dv sin_angle_over_scale
#define dy_dv cos_angle_over_scale
// Compute the first pixel in the destination surface (su, sv)
int su = destrect->left - mx,
sv = destrect->top - my;
// Compute the first pixel in the source surface (sx, sy)
fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
// Transform to the source surface coordinates
sx += srcsurf.dwWidth / 2;
sy += srcsurf.dwHeight / 2;
// Do the blit
for (int v = 0; v < h; v++)
{
// (x,y) is the current pixel that has to be copied
fix x = sx,
y = sy;
for (int u = 0; u < w; u++, d += 2)
{
// (ix,iy) is the integer location of the current pixel
int ix = (int)x, iy = (int)y;
// Check if (ix,iy) is in the image
if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
{
// Compute the pixels location in memory
s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + (ix << 1);
// If not mask_color then write the pixel
if (*(WORD *)s != (WORD)mask_color)
*(WORD *)d = *(WORD *)s;
}
// Update (x,y)
x += dx_du;
y += dy_du;
}
// Update the destination pointer to the next scanline
d += destsurf.lPitch - (w << 1);
// (sx,sy) is moved one scanline
sx += dx_dv;
sy += dy_dv;
}
// Unlock surfaces
src->Unlock(0);
dest->Unlock(destrect);
}
void rotated_blit24(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
{
// Define: (x,y) is a point in the source surface,
// (u,v) is a point in the destination surface,
// (0,0) corresponds to the center of the image in both surfaces.
//
// A point in the source surface is then given as:
//
// (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
DDSURFACEDESC2 destsurf, srcsurf;
BYTE *d, *s;
ASSERT(scale != (fix)0);
// Lock surfaces
srcsurf.dwSize = sizeof(srcsurf);
while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
destsurf.dwSize = sizeof(destsurf);
while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
// Get destination pointer
d = (BYTE *)destsurf.lpSurface;
// Get size of area to write
int w = destrect->right - destrect->left,
h = destrect->bottom - destrect->top;
// Compute some frequently used variables
fix cos_angle_over_scale = cos(angle) / scale,
sin_angle_over_scale = sin(angle) / scale;
// Compute (dx,dy) for (du,dv)=(1,0)
#define dx_du cos_angle_over_scale
#define dy_du -sin_angle_over_scale
// Compute (dx,dy) for (du,dv)=(0,1)
#define dx_dv sin_angle_over_scale
#define dy_dv cos_angle_over_scale
// Compute the first pixel in the destination surface (su, sv)
int su = destrect->left - mx,
sv = destrect->top - my;
// Compute the first pixel in the source surface (sx, sy)
fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
// Transform to the source surface coordinates
sx += srcsurf.dwWidth / 2;
sy += srcsurf.dwHeight / 2;
// Do the blit
for (int v = 0; v < h; v++)
{
// (x,y) is the current pixel that has to be copied
fix x = sx,
y = sy;
for (int u = 0; u < w; u++, d += 3)
{
// (ix,iy) is the integer location of the current pixel
int ix = (int)x, iy = (int)y;
// Check if (ix,iy) is in the image
if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
{
// Compute the pixels location in memory
s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + (ix << 1) + ix;
// If not mask_color then write the pixel
if ((*(DWORD *)s & 0xffffff) != (DWORD)mask_color)
*(WORD *)d = *(WORD *)s, d[2] = s[2];
}
// Update (x,y)
x += dx_du;
y += dy_du;
}
// Update the destination pointer to the next scanline
d += destsurf.lPitch - (w << 1) - w;
// (sx,sy) is moved one scanline
sx += dx_dv;
sy += dy_dv;
}
// Unlock surfaces
src->Unlock(0);
dest->Unlock(destrect);
}
void rotated_blit32(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
{
// Define: (x,y) is a point in the source surface,
// (u,v) is a point in the destination surface,
// (0,0) corresponds to the center of the image in both surfaces.
//
// A point in the source surface is then given as:
//
// (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
DDSURFACEDESC2 destsurf, srcsurf;
BYTE *d, *s;
ASSERT(scale != (fix)0);
// Lock surfaces
srcsurf.dwSize = sizeof(srcsurf);
while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
destsurf.dwSize = sizeof(destsurf);
while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
// Get destination pointer
d = (BYTE *)destsurf.lpSurface;
// Get size of area to write
int w = destrect->right - destrect->left,
h = destrect->bottom - destrect->top;
// Compute some frequently used variables
fix cos_angle_over_scale = cos(angle) / scale,
sin_angle_over_scale = sin(angle) / scale;
// Compute (dx,dy) for (du,dv)=(1,0)
#define dx_du cos_angle_over_scale
#define dy_du -sin_angle_over_scale
// Compute (dx,dy) for (du,dv)=(0,1)
#define dx_dv sin_angle_over_scale
#define dy_dv cos_angle_over_scale
// Compute the first pixel in the destination surface (su, sv)
int su = destrect->left - mx,
sv = destrect->top - my;
// Compute the first pixel in the source surface (sx, sy)
fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
// Transform to the source surface coordinates
sx += srcsurf.dwWidth / 2;
sy += srcsurf.dwHeight / 2;
// Do the blit
for (int v = 0; v < h; v++)
{
// (x,y) is the current pixel that has to be copied
fix x = sx,
y = sy;
for (int u = 0; u < w; u++, d += 4)
{
// (ix,iy) is the integer location of the current pixel
int ix = (int)x, iy = (int)y;
// Check if (ix,iy) is in the image
if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
{
// Compute the pixels location in memory
s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + (ix << 2);
// If not mask_color then write the pixel
if (*(DWORD *)s != (DWORD)mask_color)
*(DWORD *)d = *(DWORD *)s;
}
// Update (x,y)
x += dx_du;
y += dy_du;
}
// Update the destination pointer to the next scanline
d += destsurf.lPitch - (w << 2);
// (sx,sy) is moved one scanline
sx += dx_dv;
sy += dy_dv;
}
// Unlock surfaces
src->Unlock(0);
dest->Unlock(destrect);
}